package org.lex.library;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;

import javax.swing.table.AbstractTableModel;

public class LibraryTableModel extends AbstractTableModel {
	private static final String[] DEFAULT_COLUMNS = { Library.NAME, Library.VERSION, Library.DESCRIPTION };
	private ArrayList<Library> data = null;
	private Comparator<Library> comparator = null;
	private String[] properties = null;
	private String[] columnNames = null;
	private int versionColumnIndex = -1;

	public LibraryTableModel() {
		this(DEFAULT_COLUMNS);
	}

	public LibraryTableModel(String... properties) {
		this(properties, LibraryTableModel.capitalize(properties));
	}

	public LibraryTableModel(String[] properties, String[] columnNames) {
		data = new ArrayList<Library>();
		this.properties = Arrays.copyOf(properties, properties.length);
		this.columnNames = Arrays.copyOf(columnNames, columnNames.length);
		this.versionColumnIndex = org.lex.utils.Arrays.firstEquals(this.properties, Library.VERSION);
	}

	public void add(Library... libs) {
		if (null == libs || 0 == libs.length)
			return;
		else {
			for (Library lib : libs)
				data.add(lib);
			sort();
		}
	}

	public void remove(Library... libs) {
		if (null == libs || 0 == libs.length)
			return;
		else {
			for (Library lib : libs)
				data.remove(lib);
			this.sort();
		}
	}

	public void setComparator(Comparator<Library> comparator) {
		if (null != comparator) {
			this.comparator = comparator;
			this.sort();
		}
	}

	private void sort() {
		if (null != comparator)
			java.util.Collections.sort(data, comparator);
		else
			java.util.Collections.sort(data);
		this.fireTableDataChanged();
	}

	public Class<?> getColumnClass(int column) {
		if (column == this.versionColumnIndex)
			return Number.class;
		else
			return Object.class;
	}

	public String getColumnName(int column) {
		return this.columnNames[column];
	}

	public int getColumnCount() {
		return this.properties.length;
	}

	public int getRowCount() {
		return data.size();
	}

	public Object getValueAt(int row, int column) {
		if (row >= this.data.size())
			return null;
		Library lib = this.data.get(row);
		return lib.get(this.properties[column]);
	}

	private static String[] capitalize(String[] properties) {
		String[] data = new String[properties.length];
		for (int i = 0, n = data.length; i < n; i++)
			data[i] = capitalize(properties[i]);
		return data;
	}

	private static String capitalize(String s) {
		if (0 == s.length())
			return s;
		StringBuilder buf = new StringBuilder(s.length());
		buf.append(s);
		buf.setCharAt(0, Character.toUpperCase(s.charAt(0)));
		for (int i = 1, n = s.length(); i < n; i++) {
			buf.setCharAt(i, Character.toLowerCase(buf.charAt(i)));
			if (Character.isWhitespace(buf.charAt(i - 1)))
				buf.setCharAt(i, Character.toUpperCase(buf.charAt(i)));
		}
		return buf.toString();
	}
}
